// utils/idCardReader.ts

/**
 * 获取默认的 WebSocket 地址
 * 根据页面协议自动选择 WS 或 WSS
 * - HTTP 环境: ws://127.0.0.1:9001
 * - HTTPS 环境: wss://127.0.0.1:9002 (如果读卡器服务支持不同端口)
 * 
 * 注意：大多数读卡器服务可能只支持 ws:// 协议
 * 如果在 HTTPS 环境下遇到问题，需要：
 * 1. 检查读卡器服务是否支持 WSS
 * 2. 或者配置读卡器服务使用相同端口但支持 WSS
 */
function getDefaultWebSocketUrl(): string {
  // 在浏览器环境中
  // if (typeof window !== 'undefined') {
  //   const isHttps = window.location.protocol === 'https:';
  //   if (isHttps) {
  //     // HTTPS 环境使用 WSS 协议
  //     // 注意：如果读卡器服务不支持 WSS，这里会连接失败
  //     // 可以尝试使用相同端口 9001，或使用专门的 WSS 端口如 9002
  //     return 'wss://127.0.0.1:9001';
  //   } else {
  //     // HTTP 环境使用 WS 协议
  //     return 'ws://127.0.0.1:9001';
  //   }
  // }
  // 服务端渲染环境：默认使用 WS
  return 'ws://127.0.0.1:9001';
}

/**
 * 身份证信息接口
 */
export interface IDCardInfo {
  cardType: string; // 卡类型
  name: string; // 姓名
  gender: string; // 性别
  nation: string; // 民族
  birthDay: string; // 出生日期 yyyyMMdd
  address: string; // 住址
  idNumber: string; // 身份证号
  issueOrg: string; // 签发机关
  effectiveDate: string; // 开始期限 yyyyMMdd
  expiryDate: string; // 结束期限 yyyyMMdd 或 "长期"
  issuesNum?: string; // 签发次数/换证次数
  passCheckID?: string; // 通行证号码/旧版外国人号码
  chineseName?: string; // 中文姓名
  certVersion?: string; // 证件版本
  nationCode?: string; // 国籍代码
  photo?: string; // 照片 base64
  frontPhoto?: string; // 正面照片 base64
  backPhoto?: string; // 反面照片 base64
}

/**
 * 读卡器状态
 */
export enum ReaderStatus {
  CONNECTING = 0, // 正在连接
  CONNECTED = 1, // 已建立连接
  CLOSING = 2, // 正在关闭连接
  CLOSED = 3, // 已关闭连接
}

/**
 * 读卡结果
 */
export interface ReadResult {
  success: boolean;
  data?: IDCardInfo;
  error?: string;
}

/**
 * 华视身份证读卡器工具类
 */
export class IDCardReader {
  private ws: WebSocket | null = null;
  private isConnected: boolean = false;
  private readTimeout: number = 10000; // 默认10秒超时
  private timeoutTimer: ReturnType<typeof setTimeout> | null = null;
  private wsUrl: string;

  constructor() {
    // 根据当前页面协议自动选择 WS 或 WSS
    this.wsUrl = getDefaultWebSocketUrl();
    //console.log('读卡器 WebSocket 地址:', this.wsUrl);
  }

  /**
   * 读取身份证（不拿起读身份证模式）
   * 直接读取当前放置在读卡器上的身份证，无需拿起再放下
   * @param onSuccess 成功回调
   * @param onError 失败回调
   * @param timeout 超时时间（毫秒），默认10000ms
   */
  public async readCard(
    onSuccess: (data: IDCardInfo) => void,
    onError: (error: string) => void,
    timeout: number = 10000
  ): Promise<void> {
    this.readTimeout = timeout;

    try {
      // 1. 连接服务
      await this.connect();

      // 2. 设置超时定时器
      this.startTimeout(onError);

      // 3. 设置消息监听
      this.setupMessageHandler(onSuccess, onError);

      // 4. 发送读卡指令（命令04：不拿起读身份证）
      this.sendReadCommand();
    } catch (error) {
      const errorMsg = error instanceof Error ? error.message : '连接失败';
      onError(errorMsg);
      this.disconnect();
    }
  }

  /**
   * 建立 WebSocket 连接
   */
  private connect(): Promise<void> {
    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(this.wsUrl);

        this.ws.onopen = () => {
          this.isConnected = true;
          //console.log('读卡器服务连接成功');
          resolve();
        };

        this.ws.onerror = (error) => {
          //console.error('WebSocket 连接错误:', error);
          reject(new Error('无法连接到读卡器服务，请确保读卡器服务已启动'));
        };

        this.ws.onclose = () => {
          this.isConnected = false;
          //console.log('读卡器服务连接已关闭');
        };

        // 连接超时处理
        setTimeout(() => {
          if (!this.isConnected) {
            reject(new Error('连接读卡器服务超时'));
            this.disconnect();
          }
        }, 5000);
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 设置消息处理器
   */
  private setupMessageHandler(
    onSuccess: (data: IDCardInfo) => void,
    onError: (error: string) => void
  ): void {
    if (!this.ws) return;

    this.ws.onmessage = (res: MessageEvent) => {
      // 清除超时定时器
      this.clearTimeout();

      const message = res.data as string;

      // 处理错误信息
      if (message === 'failed to obtain ID card information') {
        onError('未能获取身份证信息，请重新放置身份证');
        this.disconnect();
        return;
      }

      // 解析身份证数据
      const allData = message.split('|');

      if (allData.length >= 17) {
        const idCardInfo: IDCardInfo = {
          cardType: allData[2] || '',
          name: allData[3] || '',
          gender: allData[4] || '',
          nation: allData[5] || '',
          birthDay: allData[6] || '',
          address: allData[7] || '',
          idNumber: allData[8] || '',
          issueOrg: allData[9] || '',
          effectiveDate: allData[10] || '',
          expiryDate: allData[11] || '',
          issuesNum: allData[14],
          passCheckID: allData[15],
          chineseName: allData[16],
          certVersion: allData[17],
          nationCode: allData[18],
          photo: allData[19]
            ? `data:image/bmp;base64,${allData[19]}`
            : undefined,
          frontPhoto: allData[20]
            ? `data:image/jpeg;base64,${allData[20]}`
            : undefined,
          backPhoto: allData[21]
            ? `data:image/jpeg;base64,${allData[21]}`
            : undefined,
        };

        onSuccess(idCardInfo);
        // 读取成功后自动断开
        this.disconnect();
      } else {
        onError(message || '读取身份证信息失败');
        this.disconnect();
      }
    };
  }

  /**
   * 发送读卡指令
   */
  private sendReadCommand(): void {
    if (!this.ws || !this.isConnected) {
      throw new Error('WebSocket 未连接');
    }

    // 使用 "04" 命令：不拿起读身份证（直接读取当前卡片）
    const command = `04?timeout=${this.readTimeout}`;
    this.ws.send(command);
    //console.log('已发送读卡指令（不拿起读身份证模式）');
  }

  /**
   * 启动超时定时器
   */
  private startTimeout(onError: (error: string) => void): void {
    this.timeoutTimer = setTimeout(() => {
      if (this.isConnected) {
        onError('读取身份证超时，请重试');
        this.disconnect();
      }
    }, this.readTimeout);
  }

  /**
   * 清除超时定时器
   */
  private clearTimeout(): void {
    if (this.timeoutTimer) {
      clearTimeout(this.timeoutTimer);
      this.timeoutTimer = null;
    }
  }

  /**
   * 断开连接
   */
  private disconnect(): void {
    this.clearTimeout();

    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }

    this.isConnected = false;
    //console.log('已断开读卡器连接');
  }

  /**
   * 获取连接状态
   */
  public getStatus(): boolean {
    return this.isConnected;
  }

  /**
   * 设置 WebSocket 服务地址
   */
  public setUrl(url: string): void {
    this.wsUrl = url;
  }
}

/**
 * 创建读卡器实例（单例模式）
 */
let readerInstance: IDCardReader | null = null;

export function useIDCardReader(): IDCardReader {
  if (!readerInstance) {
    readerInstance = new IDCardReader();
  }
  return readerInstance;
}

/**
 * 检查当前环境协议
 */
export function getCurrentProtocol(): 'http' | 'https' {
  if (typeof window !== 'undefined') {
    return window.location.protocol === 'https:' ? 'https' : 'http';
  }
  return 'http';
}

/**
 * 获取推荐的读卡器服务地址
 */
export function getRecommendedReaderUrl(): string {
  const protocol = getCurrentProtocol();
  if (protocol === 'https') {
    return 'wss://127.0.0.1:9001';
  }
  return 'ws://127.0.0.1:9001';
}

/**
 * 检查读卡器服务连接
 * 用于在使用前测试连接
 */
export async function checkReaderConnection(): Promise<{
  success: boolean;
  error?: string;
  protocol?: string;
}> {
  return new Promise((resolve) => {
    const wsUrl = getDefaultWebSocketUrl();
    const protocol = getCurrentProtocol();
    
    try {
      const ws = new WebSocket(wsUrl);
      
      const timeout = setTimeout(() => {
        ws.close();
        resolve({
          success: false,
          error: '连接读卡器服务超时',
          protocol: protocol,
        });
      }, 3000);

      ws.onopen = () => {
        clearTimeout(timeout);
        ws.close();
        resolve({
          success: true,
          protocol: protocol,
        });
      };

      ws.onerror = () => {
        clearTimeout(timeout);
        resolve({
          success: false,
          error: `无法连接到读卡器服务 (${wsUrl})`,
          protocol: protocol,
        });
      };
    } catch (error) {
      resolve({
        success: false,
        error: error instanceof Error ? error.message : '连接失败',
        protocol: protocol,
      });
    }
  });
}

/**
 * HTTPS 环境使用说明
 * 
 * 在 HTTPS 环境下使用身份证读卡器需要注意：
 * 
 * 1. WebSocket 协议匹配：
 *    - HTTP 页面必须使用 ws:// 协议
 *    - HTTPS 页面必须使用 wss:// 协议（WebSocket Secure）
 *    - 混合使用会被浏览器阻止（Mixed Content 安全策略）
 * 
 * 2. 读卡器服务配置：
 *    - 确认读卡器服务是否支持 WSS 协议
 *    - 某些读卡器服务只支持 WS 协议，需要升级或配置
 *    - 可能需要为 WSS 配置 SSL 证书
 * 
 * 3. 常见读卡器服务 WSS 配置：
 *    - 华视读卡器：检查服务配置文件是否启用 WSS
 *    - 神思读卡器：查看服务设置中的安全选项
 *    - 通用方案：使用支持 WSS 的代理服务
 * 
 * 4. 如果读卡器服务不支持 WSS：
 *    - 方案A：将应用改为 HTTP 访问（仅开发环境）
 *    - 方案B：使用 Nginx/Apache 作为 WSS 代理
 *    - 方案C：联系读卡器厂商获取支持 WSS 的服务版本
 * 
 * 5. 证书信任（如果读卡器服务使用自签名证书）：
 *    - 浏览器访问 wss://127.0.0.1:9001 测试连接
 *    - 如提示证书错误，按照浏览器提示信任证书
 *    - 信任后刷新应用页面即可正常使用
 */
